package renpyas3.view.instructions
{
	import flash.display.Bitmap;
	import flash.display.Loader;
	import flash.events.Event;
	import flash.utils.setTimeout;
	import org.osflash.thunderbolt.Logger;
	import renpyas3.model.RenpyPlayerModel;
	import renpyas3.view.components.TransitionEngine;
	import renpyas3.view.RenpyPlayer;
	
	/**
	 * show a foreground image, usually a character
	 */
	public class ViewInstruction_show extends ViewInstruction
	{
		public static const NAME:String = "show";
		
		private var _view:RenpyPlayer;
		private var _model:RenpyPlayerModel;
		private var _transitionName:String;
		
		public function ViewInstruction_show() 
		{
			
		}
		
		/**
		 * execute a the code for this command, altering RenpyPlayerViewState
		 * @param	view  is the whole set of view state variables and operations that make up the VIEW
		 * @param	model the data needed to play a renpy novel
		 * @param	params   extra data for some instructions
		 */
		override public function execute(view:RenpyPlayer, model:RenpyPlayerModel, params:Object=null):void
		{
			_view = view;
			_model = model;
			_transitionName = params.transition;

			var imgToShowName:String = params.imageName;
			var imgToShowPtr:Bitmap;
			
			if (model.currentScreen.imagesForThisScreen[imgToShowName])
			{
				if (view.imagesLayer.numChildren > 0)
				{
					view.imagesLayer.removeChildAt(0);
				}
				
				
				if (model.currentScreen.imagesForThisScreen[imgToShowName].isAnimation)
				{
					//is animation
					var animFramesFileNames:Vector.<String> = model.currentScreen.imagesForThisScreen[imgToShowName].animFramesFileNames;
					var animFramesDurations:Vector.<Number> = model.currentScreen.imagesForThisScreen[imgToShowName].animFramesDurations;
					var currDelayToShowInSecs:Number = 0;
					var currImage:Bitmap;
					Logger.info("ViewInstruction_show::execute is animation --framesCount:"+animFramesFileNames.length); 
					for (var i:uint = 0; i < animFramesFileNames.length; i++)
					{
						var pathAndFilename:String = animFramesFileNames[i];
						currImage = _model.assetsLoader.getBitmap(pathAndFilename) as Bitmap;
						Logger.info("ViewInstruction_show::execute, schedule anim pathAndFilename:"+pathAndFilename+",  currImage:"+currImage.name+",  delay:"+currDelayToShowInSecs); 
						setTimeout(showImage, currDelayToShowInSecs*1000, currImage);
						currDelayToShowInSecs += animFramesDurations[i];
					}
					setTimeout(finishAnimation, currDelayToShowInSecs*1000);
				}
				else
				{
					//is single image
					//imgToShowPtr = model.currentScreen.imagesForThisScreen[imgToShowName].loader;
					pathAndFilename = model.currentScreen.imagesForThisScreen[imgToShowName].pathAndFilename;
					imgToShowPtr = _model.assetsLoader.getBitmap(pathAndFilename) as Bitmap;

					Logger.info("ViewInstruction_show::execute is not animation, pathAndFilename:"+pathAndFilename); 

					if (imgToShowPtr)
					{
						showImage(imgToShowPtr);
						
						if (_transitionName == "")
						{						
							//all done in this command
							afterNewImageAdded();		
						}
						else
						{
							_view.imagesLayer.alpha = 0;
							_view.transtionEngine.startTransition(_transitionName, _view.imagesLayer);
							_view.transtionEngine.addEventListener(TransitionEngine.TRANSITION_FINISHED, handleNewImageFadeInFinished,false,0,true);
						}
					}
				}
			}
				
		}			
		
		private function finishAnimation():void
		{
			if (_view == null)
			{
				//might get here because some animation frames where schedulled and the abort function
				//was called before showing some of them
				return;
			}
			
			//all done in this command
			_view.instructionsProcessor.instructionFinished();		

			//clean references
			_view = null;
			_model = null;
		}
		
		private function showImage(imgToShowPtr:Bitmap):void
		{
			if (_view == null)
			{
				//might get here because some animation frames where schedulled and the abort function
				//was called before showing some of them
				return;
			}
			Logger.info("ViewInstruction_show::showImage:"+imgToShowPtr.name); 
			
			//remove current image
			if (_view.imagesLayer.numChildren > 0)
			{
				_view.imagesLayer.removeChildAt(0);
			}
			
			//and show new
			var scaleFactorX:Number = _view.imagesLayer.stage.stageWidth / _model.options.screenWidth;
			var scaleFactorY:Number = _view.imagesLayer.stage.stageHeight/ _model.options.screenHeight;
			imgToShowPtr.scaleX = scaleFactorX;
			imgToShowPtr.scaleY = scaleFactorY;
			
			//try to apply smoothing
			if (imgToShowPtr as Bitmap)
			{
				imgToShowPtr.smoothing = true;
			}
			
			_view.imagesLayer.addChild(imgToShowPtr);
			imgToShowPtr.x = ((800 - imgToShowPtr.width) / 2);
			imgToShowPtr.y = (600 - imgToShowPtr.height);
		}
		
		private function handleNewImageFadeInFinished(e:Event):void
		{
			Logger.info("ViewInstruction_show::handleNewImageFadeInFinished called"); 
			_view.transtionEngine.removeEventListener(TransitionEngine.TRANSITION_FINISHED, handleNewImageFadeInFinished);
			afterNewImageAdded();
		}

		/**
		 * called when fade in of the new image
		 * is finished (if the transition was "" it will show straightaway
		 * without transition and still call this to finish and clean pointers
		 */
		private function afterNewImageAdded():void
		{
			Logger.info("ViewInstruction_show::afterNewImageAdded called");
			
			//all done in this command
			_view.instructionsProcessor.instructionFinished();	
			
			//clean references
			_view = null;
			_model = null;
		}

		/**
		 * finish immediately, FastForward actions
		 */
		override public function abort():void
		{
			Logger.info("ViewInstruction_show::abort called");
			if (_view)
			{
				if (_transitionName != "")
				{
					//is is still animating
					if (_view.transtionEngine.hasEventListener(TransitionEngine.TRANSITION_FINISHED))
					{
						Logger.info("ViewInstruction_show::abort is is still animating");
						_view.transtionEngine.removeEventListener(TransitionEngine.TRANSITION_FINISHED, handleNewImageFadeInFinished);
						_view.transtionEngine.fforwardTransition();
						_view.imagesLayer.alpha = 1;
					}
				}

				afterNewImageAdded()
			}
		}

	}
}